/**
 * 菜单类 无极菜单可以无限制连级
 * elem dom节点
 * data 数据源 
 * singleClick单击事件
 * hoverEvent hover事件
 * contextmenu 右键菜单（后续加入）
 * leave 鼠标画出事件
 * gaps 为间距
 * direction 为子菜单定位的方向，left,right,top,bottom，默认为left
 * 实例地址 https://gitee.com/SimonaGo/infinite-menu
 */
 class Menu {
    constructor(params) {
        this.params = new Proxy(params, {
            get: function (target, propKey) {
                if (!Reflect.has(target, propKey)) {
                    Reflect.set(target, propKey, false); //更改参数的默认值为false
                    return Reflect.get(target, propKey);
                } else {
                    return Reflect.get(target, propKey);
                }
            },
        });
        this.checkParams();
        this.pNodes = new Set([]);
        this.childNodes = new Set([]);
        this.uuid = null;
        this.resdata = []; // 结构化数据
        this.currentData = {};
        this.showStyle = this.params.showStyle; // 菜单闭合方式：auto同时只存在一个菜单，manual菜单闭合由传入决定，mixin菜单组合式展开闭合
    }
    checkParams() {
        if (!this.params.elem) {
            throw new Error("Expected a Dom node");
        }
        if (!this.params.data) {
            throw new Error("Expected a data source");
        }
    }
    /**
     * 保证节点ID唯一
     * @returns 生成唯一ID,GUID的总数为2^128（3.4×10^38）个
     */
    uuidMade() {
        this.uuid = this.S4() + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + "-" + this.S4() + this.S4() + this.S4();
        return this.uuid;
    }
    /**
     * 随机数
     * @returns
     */
    S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    /**
     * 构造父节点
     * @param {*} param
     * @param {*} uuid 节点唯一ID
     */
    parentNode(param, uuid) {
        let elem = this.params.elem;
        let menuhtml = `
                       <li  id= ${uuid}    title="${param.name}" class="root">
                           <i class="iconfont ${param.prefix}" ></i>      
                           ${param.name}
                           <i class="iconfont ${param.suffix}" ></i>
                           <ul class="wrapper-menulist-root"></ul>                                                                                                      
                       </li>
                  `;
        $("#" + `${elem}`).append(menuhtml);
        this.callback(param, uuid, param);
        if (param.children) {
            this.childrenNode(param.children, uuid);
        }
    }
    /**
     * 构造子节点
     * @param {*} node
     * @param {*} uuid 节点唯一ID
     */
    childrenNode(node, uuid) {
        for (let item of node) {
            let cid = this.uuidMade();
            let childmenuhtml = `
                 <li  id=${cid}  title="${item.name}">
                     <i class="iconfont ${item.prefix}" ></i>      
                     ${item.name}
                     <i class="iconfont ${item.suffix}" ></i>
                     <ul class="wrapper-menulist-root"></ul>                                                                                                     
                 </li>
             `;
            $(`#${uuid} > .wrapper-menulist-root`).append(childmenuhtml);

            this.callback(node, cid, item);
            if (item.children && item.children.length) {
                this.childrenNode(item.children, cid);
            }
        }
    }
    /**
     * 结构化数据
     */
    StructuralData(orignData) {
        for (let i = 0; i < orignData.length; i++) {
            let id = orignData[i].id,
                children = null;
            if (id) {
                children = orignData.filter(res => {
                    return res.parentId == id;
                });
            }
            if (!orignData[i].parentId) {
                this.resdata.push(orignData[i]);
            }
            if (children && children.length) {
                orignData[i].children = children;
                this.StructuralData(children);
            }
        }
    }
    /**
     * 回调
     * @param {*} param
     * @param {*} uuid
     */
    callback(param, uuid, curdata) {
        const that = this;
        param.open = false;
        if (this.params.click) {
            $(`#${uuid}`).on("click", function (event) {
                event.stopPropagation();
                event.stopImmediatePropagation();
                that.currentData = that.params.data.find(res => res.id === curdata.id);
                let direction = null;
                if (that.params.direction == "top") {
                    const parents = $(`#${uuid}`).parents()[1];
                    const params = $(parents).attr("id");
                    if (params && params.search("-root")) {
                        direction = "left";
                    }
                }
                that.toggleShow(uuid, direction);
                that.params.click(that.currentData, $(`#${uuid}`));
            });
        }
        if (this.params.hover) {
            $(`#${uuid}`).on("mouseenter", function (event) {
                event.stopPropagation();
                event.stopImmediatePropagation();
                that.currentData = that.params.data.find(res => res.id === curdata.id);
                that.params.hover(that.currentData, $(`#${uuid}`));
            });
        }
        if (this.params.leave) {
            $(`#${uuid}`).on("mouseout", function (event) {
                event.stopPropagation();
                event.stopImmediatePropagation();
                that.currentData = that.params.data.find(res => res.id === curdata.id);
                that.params.leave(that.currentData, $(`#${uuid}`));
            });
        }
    }
    /**
     * 初始化样式
     * @param {*} uuid
     */
    initStyle(uuid) {
        $(`#${uuid}  .wrapper-menulist-root`).css({
            display: "none",
            opacity: 0,
            width: "max-content",
            overflow: "hidden",
        });
    }
    /**
     * 切换动画
     * @param {*} uuid
     */
    toggleShow(uuid, way) {
        const width = $(`#${uuid}> .wrapper-menulist-root`).width();
        const left = $(`#${uuid}`).width(),
            gaps = this.params.gaps || 10,
            direction = way || this.params.direction || "left";
        $(`#${uuid} > .wrapper-menulist-root li`).css({
            width: "max-content",
        });
        $(`#${uuid} > .wrapper-menulist-root`).toggle();
        $(`#${uuid} > .wrapper-menulist-root`).css({
            [direction]: left,
            width: 0,
            overflow: "hidden",
        });
        $(`#${uuid} > .wrapper-menulist-root`).animate(
            {
                opacity: 1,
                width: width,
                [direction]: left + gaps,
            },
            function () {
                $(this).css("overflow", "visible");
            }
        );
        if ($(`#${uuid} > .wrapper-menulist-root`).css("display") === "none") {
            this.initStyle(uuid);
        }
        this.showOrclose(uuid);
    }
    showOrclose(uuid) {
        const style = this.showStyle;
        let showstyle = false,
            auto = [],
            manual = [];

        if (style && style.auto) {
            showstyle = "auto";
        } else if (style && style.manual) {
            showstyle = "manual";
        } else if (style && style.mixin) {
            auto = style.mixin.auto;
            manual = style.mixin.manual;
            showstyle = "mixin";
        } else {
            showstyle = "auto";
        }
        switch (showstyle) {
            case "auto":
                $(`#${uuid}`).siblings().find(".wrapper-menulist-root").css({
                    display: "none",
                    opacity: 0,
                    width: "max-content",
                    overflow: "hidden",
                });
                break;
            case "mixin":
                break;
        }
    }
}

/**
 * 垂直菜单
 */
class VerticalLine extends Menu {
    constructor(...args) {
        super(...args);
    }
    /**
     * 初始化菜单方法
     */
    initVerticalMenus() {
        const data = this.params.data;
        const cloneData = JSON.parse(JSON.stringify(data));
        super.StructuralData(cloneData);
        this.menuType = "Vertical";
        if (this.resdata) {
            for (let item of this.resdata) {
                let uuid = super.uuidMade() + "-root";
                this.parentNode(item, uuid);
            }
        }
    }
}

/**
 * 水平菜单
 */
class HorizontalLine extends Menu {
    constructor(...args) {
        super(...args);
    }
    initHorizonMenus() {
        const data = this.params.data;
        const cloneData = JSON.parse(JSON.stringify(data));
        super.StructuralData(cloneData);
        if (this.resdata) {
            for (let item of this.resdata) {
                let uuid = super.uuidMade();
                this.parentNode(item, uuid);
            }
        }
    }
    /**
     * 构造父节点
     * @param {*} param
     * @param {*} uuid 节点唯一ID
     */
    parentNode(param, uuid) {
        let elem = this.params.elem;
        let menuhtml = `
                   <li  id=${uuid}  title="${param.name}">
                       <i class="iconfont ${param.prefix}" ></i>      
                       ${param.name}
                       <i class="iconfont ${param.suffix}" ></i>
                       <ul class="wrapper-menulist-root"></ul>                                                                                                      
                   </li>
              `;
        $("#" + `${elem}`).append(menuhtml);
        this.callback(param, uuid, param);
        if (param.children) {
            this.childrenNode(param.children, uuid);
        }
    }
}
